<?php
namespace app\api\controller;

use app\api\model\Order;
use app\api\service\OrderService;
use app\api\service\VpayService;
use app\common\controller\Api;
use think\facade\Log;
use think\facade\Cache;
use app\api\model\App as AppModel;
use think\exception\HttpResponseException;

/**
 * 应用API控制器
 * 处理设备心跳、订单创建、支付推送等业务
 */
class App extends Api
{

    /**
     * 设备心跳接口
     * @param VpayService $vpayService
     */
    public function heart(VpayService $vpayService)
    {
        try {
            $data = $this->request->get();
            $vpayService->checkDeviceParams($data);
            $device = $vpayService->getDevice($data['device_id']);
            $vpayService->checkSign($data, $device->appsecret);
            $vpayService->setHeartbeat($device);
            $this->success('心跳成功', '', 200);
        }catch(HttpResponseException $e){
            throw $e;
        }catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }

    /**
     * 支付推送接口
     * @param OrderService $orderService
     * @param VpayService $vpayService
     */
    public function push(OrderService $orderService, VpayService $vpayService)
    {
        try {
            $data = $this->request->get();
            $vpayService->checkDeviceParams($data);
            $device = $vpayService->getDevice($data['device_id']);
            $vpayService->checkSign($data, $device->appsecret);
            $vpayService->setHeartbeat($device);
            $orderService->callback($device, $data['type'], $data['price'], $data['time'] ?? null);
            $this->success('推送成功', '', 200);
        } catch(HttpResponseException $e){
            throw $e;
        }catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }

    /**
     * 创建订单接口
     * @param OrderService $orderService
     * @param VpayService $vpayService
     */
    public function createOrder(OrderService $orderService, VpayService $vpayService)
    {
        try {
            $data = $this->request->post();
            $this->validateCreateOrderParams($data);
            
            $app = $this->validateAndGetApp($data['appid'], $vpayService);
            $vpayService->checkSign($data, $app->appsecret);
            
            $device = $this->getAvailableDevice($data, $vpayService);
            $order = $orderService->createOrder($app, $data['amount'], $data['type'], $data['trade_no'], $device->id);
            
            $responseData = $this->buildOrderResponse($order, $device);
            $this->success('下单成功', $responseData);
        } catch(HttpResponseException $e){
            throw $e;
        }catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }

    /**
     * 关闭订单接口
     * @param OrderService $orderService
     * @param VpayService $vpayService
     */
    public function closeOrder(OrderService $orderService, VpayService $vpayService)
    {
        try {
            $data = $this->request->post();
            $this->validateCloseOrderParams($data);
            
            $this->validateAndGetApp($data['appid'], $vpayService);
            $orderService->closeOrder($data['appid'], $data['trade_no']);
            $this->success('订单关闭成功');
        }catch(HttpResponseException $e){
            throw $e;
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }
    

    /**
     * 查询可用设备接口
     * @param VpayService $vpayService
     */
    public function queryAvailableClient(VpayService $vpayService)
    {
        try {
            $data = $this->request->get();
            $this->validateAndGetApp($data['appid'], $vpayService);
            
            $device = $vpayService->getIdleClient();
            $responseData = [];
            if (!empty($device)) {
                $responseData = [
                    'id' => $device->id,
                    'alipay' => $device->alipay,
                    'wechat' => $device->wechat,
                ];
            }
            $this->success('查询成功', $responseData);
        } catch(HttpResponseException $e){
            throw $e;
        }catch (\Exception $e) {
            $this->error($e->getMessage());
        }
    }

    /**
     * 验证并获取应用信息
     * @param string $appid
     * @param VpayService $vpayService
     * @return AppModel
     * @throws \Exception
     */
    private function validateAndGetApp(string $appid, VpayService $vpayService): AppModel
    {
        $vpayService->checkAppParams(['appid' => $appid]);
        $app = AppModel::where('appid', $appid)->find();
        if (empty($app)) {
            throw new \Exception('appid不存在');
        }
        return $app;
    }

    /**
     * 验证创建订单参数
     * @param array $data
     * @throws \Exception
     */
    private function validateCreateOrderParams(array $data): void
    {
        $requiredParams = ['appid', 'amount', 'type', 'trade_no'];
        foreach ($requiredParams as $param) {
            if (!isset($data[$param]) || $data[$param] === '') {
                throw new \Exception("缺少参数{$param}");
            }
        }
        
        if (!in_array($data['type'], [Order::PAY_TYPE_ALIPAY, Order::PAY_TYPE_WECHAT])) {
            throw new \Exception('不支持的支付类型');
        }
        
        if ($data['amount'] <= 0) {
            throw new \Exception('订单金额必须大于0');
        }
    }

    /**
     * 验证关闭订单参数
     * @param array $data
     * @throws \Exception
     */
    private function validateCloseOrderParams(array $data): void
    {
        if (!isset($data['trade_no']) || $data['trade_no'] === '') {
            throw new \Exception('缺少参数trade_no');
        }
        if (!isset($data['appid']) || $data['appid'] === '') {
            throw new \Exception('缺少参数appid');
        }
    }

    /**
     * 获取可用设备
     * @param array $data
     * @param VpayService $vpayService
     * @return \app\api\model\Device
     * @throws \Exception
     */
    private function getAvailableDevice(array $data, VpayService $vpayService)
    {
        if (isset($data['device_id'])) {
            $device = $vpayService->getDevice($data['device_id']);
            $this->validateDeviceStatus($device, $data['type']);
            return $device;
        } else {
            $device = $vpayService->getIdleClient($data['type']);
            if (empty($device)) {
                throw new \Exception('没有可用的设备');
            }
            return $device;
        }
    }

    /**
     * 验证设备状态和支付类型支持
     * @param \app\api\model\Device $device
     * @param string $payType
     * @throws \Exception
     */
    private function validateDeviceStatus($device, string $payType): void
    {
        if (!$device->online_status) {
            throw new \Exception('设备不在线');
        }
        
        switch ($payType) {
            case Order::PAY_TYPE_ALIPAY:
                if (empty($device->alipay)) {
                    throw new \Exception('设备不支持支付宝');
                }
                break;
            case Order::PAY_TYPE_WECHAT:
                if (empty($device->wechat)) {
                    throw new \Exception('设备不支持微信');
                }
                break;
        }
    }

    /**
     * 构建订单响应数据
     * @param \app\api\model\Order $order
     * @param \app\api\model\Device $device
     * @return array
     */
    private function buildOrderResponse($order, $device): array
    {
        return [
            'trade_no' => $order->trade_no,
            'amount' => $order->amount,
            'device_id' => $order->device_id,
            'type' => $order->pay_type,
            'qrcode' => $order->pay_type == Order::PAY_TYPE_ALIPAY ? $device->alipay : $device->wechat,
            'expire_time' => $order->expire_time,
        ];
    }
}